<template>
  <div></div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import * as dat from "dat.gui";

const gui = new dat.GUI();

let scene, camera, renderer;
// let mesh;
let mixer, cameraMixer;
let controls;
let clock = new THREE.Clock();
const vector = new THREE.Vector3(); //三维坐标对象
//相机位置
const cameraX = 0;
const cameraY = 5;
const cameraZ = 20;

initRenderer();
initScence();
initLight();
initAxesHelper();
initMeshes();
initCamera();
initControls();
animate();
initControlUI();

//初始化渲染器
function initRenderer() {
  renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true;
  renderer.outputEncoding = THREE.sRGBEncoding; //渲染模型
  document.body.appendChild(renderer.domElement);
}

//初始化场景
function initScence() {
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0xe0e0e0);
  scene.fog = new THREE.Fog(0xe0e0e0, 20, 100); //定义每个物体的雾的类型
}

//初始化灯光
function initLight() {
  scene.add(new THREE.AmbientLight(0xffffff, 0.5));

  const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
  directionalLight.position.set(10, 10, 5);
  directionalLight.castShadow = true;
  scene.add(directionalLight);
}

//初始化坐标轴
function initAxesHelper() {
  const axesHelper = new THREE.AxesHelper(10);
  scene.add(axesHelper);
  const grid = new THREE.GridHelper(200, 40, 0x000000, 0x000000);
  grid.material.opacity = 0.2;
  grid.material.transparent = true;
  scene.add(grid);
}

//初始化物体
function initMeshes() {
  //添加平面
  const plane = new THREE.Mesh(
    new THREE.PlaneGeometry(2000, 2000),
    new THREE.MeshStandardMaterial({
      color: 0x999999,
      depthWrite: false,
    })
  );
  plane.rotation.x = -Math.PI / 2;
  plane.receiveShadow = true;
  scene.add(plane);

  //添加球体
  const sphereGeometry = new THREE.SphereGeometry(1, 20, 20);
  const sphereMaterial = new THREE.MeshStandardMaterial();
  const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
  sphere.castShadow = true;
  sphere.position.set(2, 2, 2);
  scene.add(sphere);

  //引入gltf模型
  const loader = new GLTFLoader();
  loader.load(
    "models/RobotExpressive.glb",
    (gltf) => {
      const model = gltf.scene;
      scene.add(model);

      //添加阴影
      model.traverse((object) => {
        if (object.isMesh) object.castShadow = true;
      });

      //创建动画
      createGUI(model, gltf.animations);
    },
    (xhr) => {
      console.log("加载完成的百分比" + (xhr.loaded / xhr.total) * 100 + "%");
    }
  );
}

//创建动画
function createGUI(model, animations) {
  const animationClip = animations.find(
    (animationClip) => animationClip.name === "Dance"
  );
  mixer = new THREE.AnimationMixer(model);
  const action = mixer.clipAction(animationClip);
  action.play();
}

//初始化相机
function initCamera() {
  camera = new THREE.PerspectiveCamera(
    45,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  camera.position.set(cameraX, cameraY, cameraZ);
}

//初始化控制器
function initControls() {
  controls = new OrbitControls(camera, renderer.domElement);
}

//开启漫游模式
function pointerLockControls(event) {
  //获取三维坐标
  vector.set(
    (event.clientX / window.innerWidth) * 2 - 1,
    -(event.clientY / window.innerHeight) * 2 + 1,
    0.5
  );
  vector.unproject(camera);
  let raycaster = new THREE.Raycaster(
    camera.position,
    vector.sub(camera.position).normalize()
  );
  let intersects = raycaster.intersectObjects(scene.children);
  if (intersects.length > 0) {
    let selected = intersects[0]; //取第一个物体
    cameraAnimation(selected.point.x, selected.point.y, selected.point.z);
  }
}

//场景移动动画
function cameraAnimation(selectedX, selectedY, selectedZ) {
  const x = selectedX - controls.target.x + camera.position.x;
  const y = selectedY - controls.target.y + camera.position.y;
  const z = selectedZ - controls.target.z + camera.position.z;

  controls.target.set(selectedX, selectedY, selectedZ); //移动相机目标坐标

  const positionKF = new THREE.VectorKeyframeTrack(
    ".position",
    [0, 1],
    [camera.position.x, camera.position.y, camera.position.z, x, y, z]
  );
  const clip = new THREE.AnimationClip("cameraMoveAction", 1, [positionKF]);
  cameraMixer = new THREE.AnimationMixer(camera);
  const action = cameraMixer.clipAction(clip);
  action.setLoop(THREE.LoopOnce);
  action.clampWhenFinished = true; //取消动画重置
  action.play();
}

//渲染场景
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
  const delta = clock.getDelta();
  if (mixer) mixer.update(delta);
  if (cameraMixer) cameraMixer.update(delta);
}

//初始化控制界面
function initControlUI() {
  const f = gui.addFolder("Controls");
  f.add({ Controls: false }, "Controls")
    .name("漫游模式")
    .onChange((val) => {
      if (val) {
        controls.enabled = false;
        window.addEventListener("click", pointerLockControls);
      } else {
        controls.enabled = true;
        window.removeEventListener("click", pointerLockControls);
      }
    });
  f.open();
}
</script>
